package fr.pud.client.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Observable;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import fr.pud.client.i18n.LanguagesConstants;

/**
 * The implementation of a Route as a list of PUDStation.
 * Apr 9, 2012 - OSE.
 * @author Simon Devineau, Adrien Hierry, Leopold Houdin, Pierre Reliquet
 *         Ecole des Mines de Nantes
 *         Route.java
 */
public class Route extends Observable implements Serializable {
    private static final long      serialVersionUID = -6014957519047699034L;
    public final static String[]   ROUTE_HEADER     = {
            LanguagesConstants.LANGUAGE
                    .getString(LanguagesConstants.STATION_NAME),
            LanguagesConstants.LANGUAGE
                    .getString(LanguagesConstants.STATION_ADDRESS),
            LanguagesConstants.LANGUAGE
                    .getString(LanguagesConstants.STATION_OPENING),
            LanguagesConstants.LANGUAGE
                    .getString(LanguagesConstants.STATION_CLOSING),
            LanguagesConstants.LANGUAGE
                    .getString(LanguagesConstants.STATION_LOADING_TIME),
            LanguagesConstants.LANGUAGE
                    .getString(LanguagesConstants.STATION_QUANTITY_REQUIRED)
                                                    };
    /**
     * The collection of PUDStation.
     */
    private Collection<PUDStation> stations;
    /**
     * The vehicle associated to the route.
     */
    private Vehicle                vehicle;

    /**
     * Initializes the stations and the Vehicle with the default constructor.
     */
    public Route() {
        this.stations = new ArrayList<PUDStation>();
        this.vehicle = new Vehicle();
    }

    /**
     * @param station
     *            the station to add
     * @return true if the station was added.
     */
    public boolean add(PUDStation station) {
        if (this.stations.add(station)) {
            this.setChanged();
            this.notifyObservers();
            return true;
        }
        return false;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Route) {
            Route r = (Route) obj;
            if (this.stations.size() != r.getStations().size()) {
                return false;
            }
            boolean isEqual = true;
            Iterator<PUDStation> it = this.stations.iterator();
            Iterator<PUDStation> it_obj = r.getStations().iterator();
            while (isEqual && it.hasNext()) {
                isEqual = it.next().equals(it_obj.next());
            }
            return isEqual;
        }
        return false;
    }

    /**
     * @return the stations.
     */
    public Collection<PUDStation> getStations() {
        return this.stations;
    }

    /**
     * @return the vehicle associated.
     */
    public Vehicle getVehicle() {
        return this.vehicle;
    }

    /**
     * @param station
     *            the station to remove.
     * @return true if the station was removed.
     */
    public boolean remove(PUDStation station) {
        if (this.stations.remove(station)) {
            this.setChanged();
            this.notifyObservers();
            return true;
        }
        return false;
    }

    /**
     * @param stations
     *            the new stations to put.
     */
    public void setStations(ArrayList<PUDStation> stations) {
        this.stations = stations;
    }

    /**
     * Replaces a vehicle by a new one.
     * @param v
     *            the new vehicle.
     */
    public void setVehicle(Vehicle v) {
        this.vehicle = v;
    }

    public String toHTML() {
        String toReturn = "";
        ArrayList<PUDStation> castStation = (ArrayList<PUDStation>) this.stations;
        for (int i = 1; i <= castStation.size(); i++) {
            if (i == 1) {
                toReturn += "<h3 style=\"color:green\">"
                        + LanguagesConstants.LANGUAGE
                                .getString(LanguagesConstants.VEHICLE_STARTING_POINT_ADDRESS)
                        + " : </h3>" + castStation.get(i - 1).toHTML();
            }
            else if (i != this.stations.size()) {
                toReturn += "<h3 style=\"color:#FFA500\">"
                        + LanguagesConstants.LANGUAGE
                                .getString(LanguagesConstants.STATION_ADDRESS)
                        + " n°" + i + " : </h3>"
                        + castStation.get(i - 1).toHTML();
            }
            else {
                toReturn += "<h3 style=\"color:red\">"
                        + LanguagesConstants.LANGUAGE
                                .getString(LanguagesConstants.VEHICLE_ENDING_POINT_ADDRESS)
                        + " : </h3>" + castStation.get(i - 1).toHTML();
            }
        }
        toReturn += "<h3 style=\"color:blue\">"
                + LanguagesConstants.LANGUAGE
                        .getString(LanguagesConstants.VEHICLE) + " : </h3>"
                + this.vehicle.toHTML();
        return toReturn;
    }

    /*
     * (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        String toReturn = "";
        ArrayList<PUDStation> castStation = (ArrayList<PUDStation>) this.stations;
        for (int i = 0; i < castStation.size(); i++) {
            if (i == 0) {
                toReturn += LanguagesConstants.LANGUAGE
                        .getString(LanguagesConstants.VEHICLE_STARTING_POINT_NAME)
                        + " : " + castStation.get(i).toString() + "\n";
            }
            else if (i != castStation.size()) {
                toReturn += LanguagesConstants.LANGUAGE
                        .getString(LanguagesConstants.STATION_ADDRESS)
                        + " n°"
                        + (i + 1)
                        + " : "
                        + castStation.get(i).toString()
                        + "\n";
            }
            else {
                toReturn += LanguagesConstants.LANGUAGE
                        .getString(LanguagesConstants.VEHICLE_ENDING_POINT_ADDRESS)
                        + " : " + castStation.get(i).toString() + "\n";
            }
        }
        toReturn += LanguagesConstants.LANGUAGE
                .getString(LanguagesConstants.VEHICLE)
                + " : "
                + this.vehicle.toString();
        return toReturn;
    }

    /**
     * @param d
     *            the document used to create the element.
     * @return the new xml element with a root name "route".
     */
    public Element toXML(Document d) {
        return this.toXML(d, "route");
    }

    /**
     * @param d
     *            the document used to create the element.
     * @param name
     *            the root name.
     * @return the new xml element with a root name "name".
     */
    public Element toXML(Document d, String name) {
        Element root = d.createElement(name);
        Iterator<PUDStation> it = this.stations.iterator();
        while (it.hasNext()) {
            root.appendChild(it.next().toXML(d));
        }
        return root;
    }
}
